#ifndef _TOOLKIT_H
#define _TOOLKIT_H

#include <iostream>
#include <sys/types.h>
#include <cmath>
#include <inttypes.h>

using namespace std;

enum VariantType {
    VT_LONG = 0x0,
    VT_BYTE,
    VT_SHORT,
    VT_FLOAT,
    VT_DOUBLE,
    VT_CHAR,
    VT_USHORT,
    VT_ULONG,
    VT_INT,
    VT_UINT,
    VT_BOOL,
    VT_PCHAR,
    VT_PVOID,
    VT_EMPTY,
    VT_LONGLONG,
    VT_ULONGLONG
};

class Variant {
public:
    Variant(): m_varType(VT_EMPTY) {
    }
    
    Variant(int16_t value): m_varType(VT_SHORT) {
        m_val.iVal = value;
    }

    VariantType m_varType;

    union {
        uint8_t bVal; // VT_BYTE
        int16_t iVal; // VT_SHORT
        int32_t lVal; // VT_LONG
        int64_t llVal; // VT_LONGLONG
        float fltVal; // VT_FLOAT
        double dblVal; // VT_DOUBLE
        char cVal; // VT_CHAR
        uint16_t uiVal; // VT_USHORT
        uint32_t ulVal; // VT_ULONG
        uint64_t ullVal; // VT_ULONGLONG
        bool blVal; // VT_BOOL
        char* pcVal; // VT_PCHAR
        void* pvVal; // VT_PVOID
    } m_val;
};

class Exception {
public:
    virtual std::string what() = 0;

    virtual ~Exception() {
    }

};

class IndexOutOfBoundsException : public Exception {
public:
    IndexOutOfBoundsException(size_t i);

    virtual ~IndexOutOfBoundsException() {
    }
    virtual std::string what();

private:
    std::string m_error;

};

class IllegalArgumentException : public Exception {
public:
    IllegalArgumentException(std::string s);

    virtual ~IllegalArgumentException() {
    }
    virtual std::string what();

private:
    std::string m_error;

};

class FileNotFoundException : public Exception {
public:
    FileNotFoundException(std::string s);

    virtual ~FileNotFoundException() {
    }
    virtual std::string what();

private:
    std::string m_error;

};

class NotSupportedException : public Exception {
public:
    NotSupportedException(std::string s = "");

    virtual ~NotSupportedException() {
    }
    virtual std::string what();

private:
    std::string m_error;

};



class Toolkit {
public:
    template <typename T>
    static void swap(T *list, int i, int j) {
        T temp = list[i];
        list[i] = list[j];
        list[j] = temp;
    }

    template <typename T>
    static void maxmin(T *list, int len, T &max, T &min);

    int64_t hashIntArray(const int *data, int size);

private:
    Toolkit(void);
    ~Toolkit(void);
};

template <typename T>
void Toolkit::maxmin(T *list, int len, T &max, T &min) {
    if(len <= 0) {
        return;
    }

    max = min = list[0];
    for(int i = 1; i < len; i++) {
        if(max < list[i]) {
            max = list[i];
        }

        if(min > list[i]) {
            min = list[i];
        }
    }
}

#endif
